<script>
import {
  TEXT,
  SELECT,
  PASSWORD,
  TEXTAREA,
  RADIO,
  DATE_PICKER,
} from '@/conf/uiTypes'
import { deepClone } from '@/utils'
export default {
  name: 'GFormCreator',
  props: {
    config: {
      type: Object, // title/items
      required: true,
    },
  },
  data() {
    return {
      ruleForm: {
        // address1: '22',
        // address2: '22',
        // address3: '22',
        // birthday: new Date(),
        // company: '22',
        // company_email: '22',
        // company_phone: '22',
        // company_type: '22',
        // contact: '22',
        // contact2: '2',
        // contact2_dep: '22',
        // contact2_name: '2',
        // contact2_phone: '22',
        // contact2_pos: '22',
        // contact_name: '2',
        // contact_phone: '222',
        // education: 'college',
        // identity_card: '112',
        // income: '22',
        // marriage: 'married',
        // mobile_phone: '22',
        // name: 'xp120',
        // phone: '22',
        // position: '22',
        // remark: '1',
        // sex: 'man',
        // trade: 'education',
      },
    }
  },
  created() {
    const { items, cards, rules } = this.config
    // 绑定表单验证器this
    for (let key in rules) {
      rules[key].forEach((r) => {
        // 若该方法是全局方法，第二次bind会失效，因为bind只能绑定一次
        if (r.validator) {
          r.validator = r.validator.bind(this)
        }
      })
    }
    if (cards) {
      cards.forEach((card) => this.reactiveFields(card.children))
    } else if (items) {
      this.reactiveFields(items)
    }
  },
  render() {
    const { title, items, rules, cards } = this.config
    const {
      ruleForm,
      $scopedSlots: { btn },
    } = this
    console.log('$scopedSlots', btn)
    return (
      <div class="form-box">
        {title && <h2>{title}</h2>}
        <el-form
          ref="form"
          attrs={{ model: ruleForm }}
          rules={rules}
          label-width="80px"
        >
          {/* 判断有没有卡片 */}
          {cards ? this.renderCards(cards) : this.renderRows(items)}
        </el-form>
        <div class="btn-bow">
          {btn ? (
            btn({ t: '我是scoped' })
          ) : (
            <div>
              <el-button type="primary" onClick={(e) => this.doSubmit()}>
                提交
              </el-button>
              <el-button onClick={(e) => this.reset()}>重置</el-button>
            </div>
          )}
        </div>
      </div>
    )
  },
  methods: {
    //响应式字段
    reactiveFields(items) {
      if (!items) return
      items.forEach((rows, rowIndex) => {
        rows.forEach((item, colIndex) => {
          //判断key在 this.ruleForm 里面的的是否存在
          if (this.ruleForm.hasOwnProperty(item.key)) {
            // 异常抛出，外部方法没有捕获的画，程序结束
            throw new Error(
              `行:${rowIndex + 1}_列${colIndex + 1}` +
                '已经存在相同的key:' +
                item.key +
                ',value:' +
                item.value
            )
          }
          // this.ruleForm[item.key] = item.value
          // Object.defineProperty 对所有key进行响应式，更改后更新
          // 无法检测到动态添加的key，访问、设置set/get都无法触发响应式
          this.$set(this.ruleForm, item.key, item.value)
        })
      })
    },
    //渲染卡片
    renderCards(cards) {
      const { renderRows } = this
      return cards.map((card) => {
        // 渲染name和children（renderRows)
        return (
          <el-card class="box-card" header={card.name}>
            {card.children && renderRows(card.children)}
          </el-card>
        )
        // 实现方式1
        // let h = this.$createElement
        // return h('el-card', { class: 'box-card' }, [
        //   h('template', { slot: 'header' }, [h('span', card.name)]),
        //   card.children && renderRows(card.children),
        // ])
        // 实现方式2
        // return (
        //   <el-card class="box-card">
        //     <template slot="header">
        //       <span>{card.name}</span>
        //     </template>
        //     {card.children && renderRows(card.children)}
        //   </el-card>
        // )
      })
    },
    //渲染行
    renderRows(rows) {
      return rows.map((rowArr) => <el-row>{this.renderColumns(rowArr)}</el-row>)
    },
    //渲染列
    renderColumns(columns) {
      return columns.map((col) => (
        <el-col span={col.colspan}>
          <el-form-item label={col.label} prop={col.key}>
            {this.renderItem(col)}
          </el-form-item>
        </el-col>
      ))
    },
    //渲染不同的元素
    renderItem(item) {
      const fd = this.ruleForm
      const attrs = item.attrs
      switch (item.type) {
        case TEXT:
        case PASSWORD:
        case TEXTAREA:
          return (
            <el-input attrs={attrs} type={item.type} v-model={fd[item.key]} />
          )
        case SELECT:
          return (
            <el-select attrs={attrs} v-model={fd[item.key]}>
              {item.options.map((opt) => (
                <el-option value={opt.value} label={opt.label} />
              ))}
            </el-select>
          )
        case DATE_PICKER:
          return (
            <el-date-picker
              attrs={attrs}
              v-model={fd[item.key]}
              type="date"
              placeholder="选择日期"
            />
          )
        case RADIO: //  {  label:'xxx' radios:[ { attrs:{},label:'xxx' }  ] }
          return item?.radios?.map((radio) => {
            // console.log('radio:', fd[item.key])
            return (
              <el-radio
                attrs={radio.attrs}
                v-model={fd[item.key]}
                label={radio.label}
              >
                {radio.title}
              </el-radio>
            )
          })
        default:
          return <h2>未匹配{item.type}</h2>
      }
    },
    // 外部验证
    valid(callback) {
      this.$refs.form.validate((valid) => {
        if (valid) {
          return callback(deepClone(this.ruleForm))
        } else {
          callback(false)
          console.log('验证失败')
          return false
        }
      })
    },
    //内部验证返回数据
    doSubmit() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          //相应数据
          return this.$emit('submit', deepClone(this.ruleForm))
        } else {
          console.log('验证失败')
          return false
        }
      })
    },
    // 通过$refs传递数据出去
    getData() {
      return deepClone(this.ruleForm)
    },
    // // 传递数据出去
    // passData() {
    //   // submit
    //   this.$emit('submit', deepClone(this.ruleForm))
    // },
    //重置
    reset() {
      this.$refs.form.resetFields()
    },
  },
}
</script>

<style lang="css" scoped>
.el-input,
.el-select,
.form-box .el-date-editor {
    width: 100%;
}

:deep(.el-card__header) {
    text-align: left;
}
.box-card {
    margin-bottom: 10px;
}
</style>
